﻿using Autofac;
using Autofac.Core;
using Autofac.Core.Registration;
using Autofac.Core.Resolving.Pipeline;
using AutoRegistDependency.Attributes;
using AutoRegistDependency.Component;
using AutoRegistDependency.Utils;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AutoRegistDependency.Implement
{
    /// <summary>
    /// dependsOn处理中间件，此中间件在循环依赖检测之间，因此dependsOn特性标记之后可以显示的避免同一接口不同实现的依赖
    /// </summary>
    internal class DependsOnMiddleware : IResolveMiddleware
    {
        private readonly ComponentDefinition _componentDefinition;
        public DependsOnMiddleware(ComponentDefinition componentDefinition)
        {
            _componentDefinition = componentDefinition;
        }

        public PipelinePhase Phase => PipelinePhase.ResolveRequestStart;

        public void Execute(ResolveRequestContext context, Action<ResolveRequestContext> next)
        {
            
            List<Parameter> parameters;
            if (context.Parameters != null)
            {
                parameters = context.Parameters.ToList();
            }
            else
            {
                parameters = new List<Parameter>();
            }
            var caches = parameters
                .Where(t => t is CacheParameter)
                .Select(t => t as CacheParameter)
                .ToList();
            CacheParameter cache = null;
            foreach (var parameter in caches) 
            {
                if (parameter.CacheType == _componentDefinition.InjectType)
                {
                    cache = parameter;
                }
                parameter.CurrentType = _componentDefinition.InjectType;
            }
            if (cache == null)
            {
                cache = new CacheParameter(_componentDefinition.InjectType, _componentDefinition.InjectType);
                parameters.Add(cache);
            }
            if(_componentDefinition.DependsOns!=null && _componentDefinition.DependsOns.Any())
            {
                foreach(DependsOnAttribute dep in  _componentDefinition.DependsOns)
                {
                    
                    var service= AutoFacHelper.GetResolveServiceKey(dep.Name,dep.Key,dep.ComponentType);
                    if (context.TryResolveService(service,out object depInstance))
                    {
                        cache.AddInstance(depInstance);
                    }
                }
            }
            context.ChangeParameters(parameters);
            next(context);
        }

    }
}
